// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.journeys

import android.annotation.SuppressLint
import android.content.Context
import android.text.SpannableStringBuilder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.google.android.material.card.MaterialCardView
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.repo.Journey
import xyz.apiote.bimba.czwek.repo.Stop.LineDecoration
import xyz.apiote.bimba.czwek.units.UnitSystem

class JourneysViewHolder(itemView: View) : ViewHolder(itemView) {
	val root: MaterialCardView = itemView.findViewById(R.id.journey)
	val startTime: TextView = itemView.findViewById(R.id.start_time)
	val lines: TextView = itemView.findViewById(R.id.lines)
	val endTime: TextView = itemView.findViewById(R.id.end_time)
	val legs: LinearLayout = itemView.findViewById(R.id.legs)

	companion object {
		fun bind(
			holder: JourneysViewHolder,
			onClickListener: (Journey, Int) -> Unit,
			journey: Journey,
			context: Context,
			inflater: LayoutInflater,
			isOpen: Boolean,
			position: Int
		) {
			holder.root.setOnClickListener {
				onClickListener(journey, position)
			}
			holder.startTime.text =
				context.getString(R.string.time, journey.startTime.hour, journey.startTime.minute)
			holder.endTime.text =
				context.getString(R.string.time, journey.endTime.hour, journey.endTime.minute)
			holder.lines.text = journey.legs.filter { it.start.vehicle.Line.name.isNotBlank() }
				.fold(SpannableStringBuilder("")) { acc, leg ->
					if (acc.isNotBlank()) {
						acc.append(" ")
					}
					val s = leg.start.vehicle.Line.decorate(
						SpannableStringBuilder(leg.start.vehicle.Line.name),
						LineDecoration.COLOUR,
						null
					)
					acc.append(s)
					acc
				}

			holder.legs.removeAllViews()
			journey.legs.forEach {
				@SuppressLint("InflateParams")
				val legView = inflater.inflate(R.layout.journey_leg, null, false)

				val legOrigin = legView.findViewById<TextView>(R.id.leg_origin)
				if (it.origin.getName().isBlank() || it.origin.getName() in arrayOf("START", "END")) {
					legOrigin.visibility = View.GONE
				} else {
					legOrigin.apply {
						text = it.origin.getName()
						visibility = View.VISIBLE
					}
				}

				val legOriginTime = legView.findViewById<TextView>(R.id.leg_origin_time)
				legOriginTime.text = context.getString(
					R.string.time,
					it.start.departureTime!!.Hour.toInt(),
					it.start.departureTime.Minute.toInt()
				)

				val legModeImage = legView.findViewById<ImageView>(R.id.leg_mode_image)
				legModeImage.setImageDrawable(it.start.vehicle.Line.icon(context))
				// TODO legModeImage.contentDescription = translate "leg mode: $mode"

				val legLine = legView.findViewById<TextView>(R.id.leg_line)
				legLine.apply {
					if (it.start.vehicle.Line.name.isBlank()) {
						visibility = View.GONE
					} else {
						visibility = View.VISIBLE
						text = it.start.vehicle.Line.name
					}
				}

				val distance = legView.findViewById<TextView>(R.id.leg_distance)
				distance.text = if (it.start.vehicle.Line.name.isBlank() && it.distance != null) {
					val us = UnitSystem.getSelected(context)
					us.toString(context, it.distance)
				} else {
					val headsign = it.start.vehicle.Headsign
					val stops = context.resources.getQuantityString(
						R.plurals.number_stops,
						it.intermediateStops.size + 1,
						it.intermediateStops.size + 1
					)

					if (headsign.isBlank()) {
						stops
					} else {
						context.getString(R.string.journey_stops_headsign, stops, headsign)
					}
				}

				val legDestination = legView.findViewById<TextView>(R.id.leg_destination)
				if (it.destination.getName().isBlank() || it.destination.getName() in arrayOf(
						"START",
						"END"
					)
				) {
					legDestination.visibility = View.GONE
				} else {
					legDestination.apply {
						text = it.destination.getName()
						visibility = View.VISIBLE
					}
				}

				val legDestinationTime = legView.findViewById<TextView>(R.id.leg_destination_time)
				legDestinationTime.text =
					context.getString(
						R.string.time,
						it.end.arrivalTime!!.Hour.toInt(),
						it.end.arrivalTime.Minute.toInt()
					)

				holder.legs.addView(legView)
			}
			holder.legs.visibility = if (isOpen) View.VISIBLE else View.GONE
		}
	}
}

class JourneysAdapter(
	private val inflater: LayoutInflater,
	private val context: Context,
	private var items: List<Journey>,
	private val onClickListener: ((Journey, Boolean) -> Unit),
) :
	RecyclerView.Adapter<JourneysViewHolder>() {
	var openCard: Int = -1

	val onClickListener2: ((Journey, Int) -> Unit) = { journey, position ->
		val previouslyOpen = openCard
		openCard = if (position == openCard) -1 else position
		notifyItemChanged(previouslyOpen)
		notifyItemChanged(position)
		onClickListener(journey, openCard == -1)
	}

	override fun onCreateViewHolder(
		parent: ViewGroup,
		viewType: Int
	): JourneysViewHolder {
		val rowView = inflater.inflate(R.layout.journey, parent, false)
		return JourneysViewHolder(rowView)
	}

	override fun onBindViewHolder(
		holder: JourneysViewHolder,
		position: Int
	) {
		JourneysViewHolder.bind(
			holder,
			onClickListener2,
			items[position],
			context,
			inflater,
			openCard == position,
			position
		)
	}

	override fun getItemCount(): Int = items.size
}